package ch.fhnw.qualiscan.core.libraries;

import java.io.Serializable;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

import ch.fhnw.qualiscan.AppObject;

import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.URIHandler;
import com.vaadin.ui.UriFragmentUtility;
import com.vaadin.ui.UriFragmentUtility.FragmentChangedEvent;
import com.vaadin.ui.UriFragmentUtility.FragmentChangedListener;
import com.vaadin.ui.Window;

import eu.livotov.tpt.TPTApplication;
import eu.livotov.tpt.i18n.TM;

/**
 * The UrlLib handles URL changes and manages the browser history. It calls the LoaderLib to change the page. 
 * @author Kevin Mettenberger, Benjamin Groehbiel
 *
 */
@SuppressWarnings("serial")
public class UrlLib implements FragmentChangedListener, Serializable {

	private Window mainWindow;
	
	private UriFragmentUtility urlHandler;
	
	public String[] currentUrl = new String[3];
	private String[] oldUrl = new String[3];
	public LoaderLib loaderLib;
	public AppObject dataObject;
	
	
	public UrlLib() {}
	
	/**
	 * This function takes care of the browser history. A history listener is attached to the main window. The fragments are set to ""
	 */
	public void initUrl() {
		loaderLib = new LoaderLib();
		mainWindow = TPTApplication.getCurrentApplication().getMainWindow();
		dataObject = (AppObject) mainWindow.getData();
		
		urlHandler = new UriFragmentUtility();
		urlHandler.addListener(this);
		mainWindow.addComponent(urlHandler);
		
		oldUrl[0] = "";
		oldUrl[1] = "";
		oldUrl[2] = "";
		
		initUriHandler();
	}
	
	/**
	 * If you want to detach the history listener from the main window, this function takes care of it.
	 */
	public void removeHistoryListener() {
		mainWindow.removeComponent(urlHandler);
		urlHandler.removeListener(this);
	}
	
	/**
	 * Reads the current url and returns it.
	 * @return returns the current url.
	 */
	public String getCurrentUrl() {
		return urlHandler.getFragment();
	}
	
	/**
	 * Reads the first fragment as a String.
	 * @return the first fragment as a string.
	 */
	public String getFirstFragment() {
		return currentUrl[0];
	}
	
	/**
	 * Read the second fragment.
	 * @return the second fragment as a string.
	 */
	public int getSecondFragment() {
		try {
			int secondParam = Integer.parseInt(currentUrl[1]);
			return secondParam;
		} catch(NumberFormatException e) {
			return -1;
		}
	}
	
	/**
	 * Read the third fragment
	 * @return the third fragment as a string.
	 */
	public String getThirdFragment() {
		String thirdParameter = currentUrl[2];
		return thirdParameter;
	}
	
	/**
	 * fragmentChanged gets called each time the parameter changes.
	 */
	public void fragmentChanged(FragmentChangedEvent source) {

		
		String[] tokens = source.getUriFragmentUtility().getFragment().split("/");
		
		// param 0: Controller parameter
		if(tokens.length >= 1 && !tokens[0].equals("")) {
			currentUrl[0] = tokens[0];
		} else {
			currentUrl[0] = "";
		}

		
		// param 1: Tab parameter
		if(tokens.length >= 2) {
			currentUrl[1] = tokens[1];
		} else {
			currentUrl[1] = "";
		}

		
		// param 2: id parameter
		if(tokens.length == 3) {
			currentUrl[2] = tokens[2];
		} else {
			currentUrl[2] = "";
		}
		
		// compare oldUrl[0] to currentUrl[0]


		if (!oldUrl[0].equals(currentUrl[0])) {
			loaderLib.loadPage(currentUrl[0]);
			if (!currentUrl[1].equals("")) {
				try {
					int param = Integer.parseInt(currentUrl[1]);
					dataObject.getCurrentPage().secondParameterChanged(param);
				} catch(NumberFormatException e) {
					NotificationLib.showError(TM.get("error"), "URL is invalid: 2 parameter");
				}
			}
			if (!currentUrl[2].equals("")) {
				try {
					dataObject.getCurrentPage().thirdParameterChanged(currentUrl[2]);
				} catch(NumberFormatException e) {
					NotificationLib.showError(TM.get("error"), "URL is invalid: 3rd parameter");
				}
			}
		}
		else {
			if(!oldUrl[1].equals(currentUrl[1]) && !currentUrl[1].equals("")) {
				try {
					int param = Integer.parseInt(currentUrl[1]);
					dataObject.getCurrentPage().secondParameterChanged(param);
				} catch(NumberFormatException e) {
					NotificationLib.showError(TM.get("error"), "URL is invalid: 2 parameter");
				}
			}
			if(!oldUrl[2].equals(currentUrl[2]) && !currentUrl[2].equals("")) {
				try {
					dataObject.getCurrentPage().thirdParameterChanged(currentUrl[2]);
				} catch(NumberFormatException e) {
					NotificationLib.showError(TM.get("error"), "URL is invalid: 3rd parameter");
				}
			}
		}

		oldUrl[0] = currentUrl[0];
		oldUrl[1] = currentUrl[1];
		oldUrl[2] = currentUrl[2];
		

	}
	
	/**
	 * Sets a new fragment with or without firing a history change event.
	 * @param url new fragment, created by fragmentsToString.
	 * @param fireEvent whether with event or whether not.
	 */
	public void setFragment(String url, boolean fireEvent) {
		urlHandler.setFragment(url, fireEvent);
	}
	
	/**
	 * Sets the first fragment to a specified String.
	 * @param pageName Name of the page - must exist in ch.fhnw.qualiscan.application.pages.
	 */
	public void setPage(String pageName) {
		currentUrl[0] = pageName;
		currentUrl[1] = "0";
		currentUrl[2] = "";
		
		String newUrl = fragmentsToString();
		setFragment(newUrl, true);
	}
	
	/**
	 * Sets the second fragment to a specified int.
	 * @param tabNumber tab number, beginning at 0.
	 */
	public void setTab(int tabNumber) {
		if(tabNumber >= 0) {
			currentUrl[1] = String.valueOf(tabNumber);
			String newUrl = fragmentsToString();
			setFragment(newUrl, true); // when set to false, history management does not work 100%. 
		}
	}
	
	/**
	 * Sets the third fragment to a specified int. T
	 * @param id third fragment as a integer.
	 */
	public void setId(int id) {
		currentUrl[2] = String.valueOf(id);
		String newUrl = fragmentsToString();
		setFragment(newUrl, true);
	}
	
	/**
	 * This function transforms currentUrl Array into a valid url string.
	 * @return new fragment.
	 */
	public String fragmentsToString() {	
		String controllerFragment;
		String tabFragment;
		String idFragment;
		
		if(!currentUrl[0].equals("")){
			controllerFragment = currentUrl[0] + "/";
		} else {
			controllerFragment = "PageNotFound/";
		}
		
		if(!currentUrl[1].equals("")) {
			tabFragment = currentUrl[1] + "/";
		} else {
			tabFragment = "";
		}
		
		if(!currentUrl[2].equals("") && !currentUrl[1].equals("")) {
			idFragment = currentUrl[2];
		} else {
			idFragment = "";
		}
		
		return controllerFragment + tabFragment + idFragment;
	}
	
	public void initUriHandler() {
		
		URIHandler uriHandler = new URIHandler() {
			public DownloadStream handleURI(URL context, String relativeUri) {
				
				return null;
			}
		};
		
		mainWindow.addURIHandler(uriHandler);
	}
	
}
